#ifndef _SDF_H_
#define _SDF_H_
#include <glm/glm.hpp>
#include <SEngine/Render/Entity/BoundingBox.h>
#include <glm/gtc/matrix_transform.hpp>


namespace SEngine
{
    class Texture3D;

    class SDF
    {
    public:
        virtual ~SDF() = default;
        
        /**
         * @brief 计算点到SDF表面的有向距离
         * @param point 世界空间中的查询点
         * @return 有向距离值。正数表示点在表面外，负数表示点在表面内
         */
        virtual float Distance(const glm::vec3& point) = 0;
        
        /**
         * @brief 获取SDF的轴对齐包围盒（AABB）
         * @param[out] minBound 包围盒最小顶点
         * @param[out] maxBound 包围盒最大顶点
         */
        virtual BoundingBox GetBounds() = 0;
        
        /**
         * @brief 应用平移变换
         * @param translation 平移向量
         */
        virtual void Translate(const glm::vec3& translation) { SetTransform(glm::translate(m_transform, translation)); }
        
        /**
         * @brief 应用旋转变换
         * @param rotation 旋转矩阵或四元数（这里使用矩阵示例）
         */
        virtual void Rotate(const glm::mat4& rotation) { SetTransform(m_transform * rotation); }
        
        /**
         * @brief 应用缩放变换
         * @param scale 缩放因子，可以是均匀或非均匀缩放
         */
        virtual void Scale(const glm::vec3& scale) { SetTransform(glm::scale(m_transform, scale)); }
        
        void SetTransform(glm::mat4 & mat) { m_transform = mat; m_invTransform = glm::inverse(mat); }

        /**
         * @brief 计算表面法线（通过梯度近似）
         * @param point 查询点
         * @param epsilon 用于数值微分的微小增量
         * @return 归一化的法线向量
         */
        virtual glm::vec3 Normal(const glm::vec3& point, float epsilon = 1e-4f)
        {
            float d = Distance(point);
            glm::vec3 n(
                Distance(point + glm::vec3(epsilon, 0, 0)) - d,
                Distance(point + glm::vec3(0, epsilon, 0)) - d,
                Distance(point + glm::vec3(0, 0, epsilon)) - d
            );
            return glm::normalize(n);
        }
        
        /**
         * @brief 判断点是否在SDF内部
         * @param point 查询点
         * @return 如果点在SDF内部（距离<0）返回true
         */
        virtual bool Inside(const glm::vec3& point)
        {
            return Distance(point) < 0.0f;
        }
        
    protected:
        // 变换矩阵，子类可以根据需要实现具体的变换逻辑
        glm::mat4 m_transform{1.0f}; // 初始化为单位矩阵
        glm::mat4 m_invTransform{1.0f};
    };

    namespace SDFUtils
    {
        std::unique_ptr<Texture3D> CreateTexture3DFromSDF(SDF & sdf);
    }

    class SphereSDF : public SDF
    {
    public:
        virtual ~SphereSDF() = default;
        virtual float Distance(const glm::vec3& point) override 
        {
            glm::vec3 p = m_invTransform * glm::vec4(point, 1.0f);
            return glm::length(p) - 1.0f;
        }

        virtual BoundingBox GetBounds() override
        {
            return BoundingBox{glm::vec3{-1.0f}, glm::vec3{1.0f}}.Transform(m_transform);
        }
    };



} // namespace SEngine


#endif